﻿namespace MSSqlSchemaDoc.Core
{
    using System;
    using System.Collections;
    using System.IO;
    using System.Reflection;
    using System.Resources;
    using System.Xml;
    using System.Xml.Schema;

    /// <summary>
    /// Contains helper methods to serialize the data structure objects.
    /// Using this serializer ensures that consistent Xml is generated.
    /// </summary>
    public static class XmlSerializer
    {
        /// <summary>
        /// Serializes a data structure object to Xml.
        /// </summary>
        /// <param name="objectToSerialize">The object to be serialized.</param>
        /// <returns>The Xml representing the object.</returns>
        public static XmlDocument SerializeDataStructureObject(object objectToSerialize)
        {
            XmlDocument xmlReturn = new XmlDocument();

            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(objectToSerialize.GetType(), MSSqlSchemaDoc.Core.Resources.XmlSettings.DefaultXmlNamespace);
            using (MemoryStream m = new MemoryStream())
            {
                serializer.Serialize(m, objectToSerialize);
                m.Seek(0, 0);
                using (StreamReader r = new StreamReader(m))
                {
                    xmlReturn.LoadXml(r.ReadToEnd());
                }
            }

            return xmlReturn;
        }

        /// <summary>
        /// Deserializes a data structure object.
        /// </summary>
        /// <param name="objectType">The type of the object to deserialize.</param>
        /// <param name="fullPath">The full path to the file, including the file name and extention.</param>
        /// <returns>The deserialized object.</returns>
        public static object DeserializeDataStructureObject(Type objectType, string fullPath)
        {
            if (!File.Exists(fullPath))
            {
                return null;
            }

            object deserializedObject;

            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(objectType, MSSqlSchemaDoc.Core.Resources.XmlSettings.DefaultXmlNamespace);
            using (FileStream fs = new FileStream(fullPath, FileMode.Open))
            {
                deserializedObject = serializer.Deserialize(fs);
            }

            return deserializedObject;
        }

        /// <summary>
        /// Generates a collection of schema sets.
        /// </summary>
        /// <returns>The collection of all possible shemas.</returns>
        public static XmlSchemaSet ConstructSchemaSet()
        {
            XmlSchemaSet schemas = new XmlSchemaSet();

            Assembly assembly = Assembly.GetExecutingAssembly();
            ResourceManager resMan = MSSqlSchemaDoc.Core.Resources.XmlSchema.ResourceManager;
            foreach (string resource in assembly.GetManifestResourceNames())
            {
                if (resource == string.Concat(resMan.BaseName, ".resources"))
                {
                    ResourceReader resReader = new ResourceReader(assembly.GetManifestResourceStream(resource));
                    IDictionaryEnumerator enumerator = resReader.GetEnumerator();

                    while (enumerator.MoveNext())
                    {
                        string key = enumerator.Key.ToString();
                        schemas.Add(null, new XmlTextReader(resMan.GetString(key), XmlNodeType.Document, null));
                    }
                }
            }

            return schemas;
        }
    }
}
